package com.lin.wx.pament.component.notify.impl;


import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.lin.wx.pament.component.PaymentService;
import com.lin.wx.pament.component.model.TransactionNotify;
import com.lin.wx.pament.component.notify.NotifyDataService;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.core.exception.ValidationException;
import com.wechat.pay.java.core.notification.NotificationParser;
import com.wechat.pay.java.core.notification.RequestParam;
import com.wechat.pay.java.service.partnerpayments.jsapi.model.Transaction;
import com.wechat.pay.java.service.refund.model.RefundNotification;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Optional;

/**
 * 、
 * 微信通知处理服务
 *
 * @author: linjiang
 * @date: 2024/12/10
 */
@Slf4j
@Service
public class WxV3ApiNotifyDataServiceImpl implements NotifyDataService {
    private final static String PRODUCT = "wechat_";
    @Autowired(required = false)
    private RSAAutoCertificateConfig config;
    @Autowired
    private List<PaymentService> paymentServiceList;

    @Override
    public TransactionNotify breforeNotify(String body) {
        // 从当前线程中获取request
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = requestAttributes.getRequest();
        // 从请求头中获取解签数据
        String wechatTimestamp = request.getHeader("Wechatpay-Timestamp");
        String wechatpayNonce = request.getHeader("Wechatpay-Nonce");
        String wechatSignature = request.getHeader("Wechatpay-Signature");
        String wechatPaySerial = request.getHeader("Wechatpay-Serial");

        // 构造 RequestParam
        RequestParam requestParam = new RequestParam.Builder()
                .serialNumber(wechatPaySerial)
                .nonce(wechatpayNonce)
                .signature(wechatSignature)
                .timestamp(wechatTimestamp)
                .body(body)
                .build();

        // 区分交易类型（支付通知或退款通知）
        JSONObject jsonObject = JSON.parseObject(body);
        JSONObject resource = jsonObject.getJSONObject("resource");
        String originalType = resource.getString("original_type");

        NotificationParser parser = new NotificationParser(config);
        TransactionNotify transactionNotify = new TransactionNotify();
        if (TRANSACTION.equals(originalType)) {
            // 以支付通知回调为例，验签、解密并转换成 Transaction
            Transaction transaction = parser.parse(requestParam, Transaction.class);
            // 数据封装
            transactionNotify.setOutTradeNo(transaction.getOutTradeNo());
            transactionNotify.setNotifyType(originalType);
            transactionNotify.setTransactionId(transaction.getTransactionId());
            transactionNotify.setThirdTransactionState(transaction.getTradeState().name());
        }

        if (REFUND.equals(originalType)) {
            RefundNotification refund = parser.parse(requestParam, RefundNotification.class);
            // 数据封装
            transactionNotify.setOutTradeNo(refund.getOutTradeNo());
            transactionNotify.setNotifyType(originalType);
            transactionNotify.setTransactionId(refund.getRefundId());
            transactionNotify.setThirdTransactionState(refund.getRefundStatus().name());
        }

        return transactionNotify;
    }

    @Override
    public JSONObject afterNotify(TransactionNotify data) {
        String tradeType = data.getTradeType();
        Optional<PaymentService> first = paymentServiceList.stream().filter(service -> service.support(tradeType.toLowerCase()))
                .findFirst();

        JSONObject respMap = new JSONObject();
        if (first.isPresent()) {
            PaymentService paymentService = first.get();
            try {
                String notifyType = data.getNotifyType();
                if (TRANSACTION.equals(notifyType)) {
                    // 处理交易回调通知
                    paymentService.doTransactionNotify(data);
                }

                if (REFUND.equals(notifyType)) {
                    // 处理退款回调通知
                    paymentService.doRefundNotify(data);
                }
                respMap.put("code", "SUCCESS");
            } catch (ValidationException e) {
                respMap.put("code", "FAIL");
                respMap.put("message", e.getMessage());
                log.error("系统解密失败！【{}】", JSON.toJSONString(respMap));
            } catch (Exception e) {
                respMap.put("code", "FAIL");
                respMap.put("message", e.getMessage());
                log.error("【业务操作】业务保存失败，【{}】", JSON.toJSONString(respMap));
            }
        } else {
            respMap.put("code", "FAIL");
            respMap.put("message", "未查询到处理微信通知的服务！");
            log.info("未查询到处理微信通知的服务！！！");
        }
        return respMap;
    }

    @Override
    public Boolean support(String support) {
        return support.startsWith(PRODUCT);
    }
}
